package cn.hy.mygame.view;

import java.util.ArrayList;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Point;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import cn.hy.mygame.entity.Bullet;
import cn.hy.mygame.entity.EmplacePlant;
import cn.hy.mygame.entity.Flower;
import cn.hy.mygame.entity.Pea;
import cn.hy.mygame.entity.SeedFlower;
import cn.hy.mygame.entity.SeedPea;
import cn.hy.mygame.entity.Sun;
import cn.hy.mygame.entity.Zombie;
import cn.hy.mygame.entity.ZombieManager;
import cn.hy.mygame.entity.EmplacePlant.PlantType;
import cn.hy.mygame.global.Config;
import cn.hy.mygame.model.BaseModel;
import cn.hy.mygame.model.Plant;
import cn.hy.mygame.model.TouchAble;

public class GameView extends SurfaceView implements SurfaceHolder.Callback,
		Runnable {
	private Canvas canvas;
	private Paint paint;
	private SurfaceHolder surfaceHolder;
	private boolean gameRunFlag;
	private static GameView gameView;
	
	private Bitmap buffer;
	private Canvas bkcCanvas;
	
	private ZombieManager zombieManager;
	
	private ArrayList<BaseModel> basemodelTempList;
	private ArrayList<BaseModel> gamelayout1;
	private ArrayList<BaseModel> gamelayout2;
	private ArrayList<BaseModel> gamelayout4plant0;
	private ArrayList<BaseModel> gamelayout4plant1;
	private ArrayList<BaseModel> gamelayout4plant2;
	private ArrayList<BaseModel> gamelayout4plant3;
	private ArrayList<BaseModel> gamelayout4plant4;
	
	private ArrayList<BaseModel> gamelayout4zombie0;
	private ArrayList<BaseModel> gamelayout4zombie1;
	private ArrayList<BaseModel> gamelayout4zombie2;
	private ArrayList<BaseModel> gamelayout4zombie3;
	private ArrayList<BaseModel> gamelayout4zombie4;
	
	private ArrayList<BaseModel> gamelayout3;
	private Thread gameThread;

	public GameView(Context context) {
		super(context);
		// TODO Auto-generated constructor stub
		paint = new Paint();
		surfaceHolder = getHolder();
		surfaceHolder.addCallback(this);
		gameRunFlag = true;
		
		gameView = this;
	}

	@Override
	public void surfaceCreated(SurfaceHolder holder) {
		// TODO Auto-generated method stub
		createElem();
		if (gameThread == null) {
			gameThread = new Thread(this);
			gameThread.start();
		}
		Log.i("life", "create");
	}

	@Override
	public void surfaceChanged(SurfaceHolder holder, int format, int width,
			int height) {
		Log.i("life", "change");
		// TODO Auto-generated method stub
	}

	@Override
	public void surfaceDestroyed(SurfaceHolder holder) {
		Log.i("life", "destory");
		// TODO Auto-generated method stub
	}
	
	private void createElem() {
		// TODO Auto-generated method stub
		Config.sunCollectX = (Config.deviceWith - Config.seedBank.getWidth())/2;
		zombieManager = new ZombieManager();
		
		buffer = Bitmap.createBitmap(Config.deviceWith, Config.deviceHeight, Bitmap.Config.ARGB_8888);
		bkcCanvas = new Canvas(buffer);
		
		basemodelTempList = new ArrayList<BaseModel>();
		gamelayout1 = new ArrayList<BaseModel>();
		
		gamelayout2 = new ArrayList<BaseModel>();
		SeedFlower seedFlower = new SeedFlower((Config.deviceWith - Config.seedBank.getWidth())/2 + Config.seedBank.getWidth() / 7, 0);
		SeedPea seedPea = new SeedPea((Config.deviceWith - Config.seedBank.getWidth())/2 + Config.seedBank.getWidth() / 7 * 2, 0);
		gamelayout2.add(seedFlower);
		gamelayout2.add(seedPea);
		gamelayout2.add(zombieManager);
		for (int i = 0; i < 5; i++) {
			for (int j = 0; j < 9; j++) {
				Config.plantPoints.put(i * 10 + j, new Point((j + 2)
						* Config.gameback.getWidth() / 11
						- Config.gameback.getWidth() / 11 / 2, (i + 1)
						* Config.gameback.getHeight() / 6));
				if (j == 0) {
					Config.raceWayYpoints[i] = (i + 1) * Config.gameback.getHeight() / 6;
				}
			}
		}
		gamelayout4plant0 = new ArrayList<BaseModel>();
		gamelayout4plant1 = new ArrayList<BaseModel>();
		gamelayout4plant2 = new ArrayList<BaseModel>();
		gamelayout4plant3 = new ArrayList<BaseModel>();
		gamelayout4plant4 = new ArrayList<BaseModel>();
		
		gamelayout4zombie0 = new ArrayList<BaseModel>();
		gamelayout4zombie1 = new ArrayList<BaseModel>();
		gamelayout4zombie2 = new ArrayList<BaseModel>();
		gamelayout4zombie3 = new ArrayList<BaseModel>();
		gamelayout4zombie4 = new ArrayList<BaseModel>();
		
		gamelayout3 = new ArrayList<BaseModel>();
	}

	@Override
	public void run() {
		// TODO Auto-generated method stub
		while (gameRunFlag) {
			long beforeDraw = System.currentTimeMillis();
			updateData();
			onDraw();
			long afterDraw = System.currentTimeMillis();
			if (afterDraw - beforeDraw < 50) {
				try {
					Thread.sleep(50 - (afterDraw - beforeDraw));
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
	}
	
	private void updateData() {
		synchronized (surfaceHolder) {
			basemodelTempList.clear();
			for (BaseModel model : gamelayout4zombie0) {
				if (!model.isAlive()) {
					basemodelTempList.add(model);
				}
			}
			for (BaseModel model : gamelayout4zombie1) {
				if (!model.isAlive()) {
					basemodelTempList.add(model);
				}
			}
			for (BaseModel model : gamelayout4zombie2) {
				if (!model.isAlive()) {
					basemodelTempList.add(model);
				}
			}
			for (BaseModel model : gamelayout4zombie3) {
				if (!model.isAlive()) {
					basemodelTempList.add(model);
				}
			}
			for (BaseModel model : gamelayout4zombie4) {
				if (!model.isAlive()) {
					basemodelTempList.add(model);
				}
			}
			for (BaseModel model : gamelayout4plant0) {
				if (!model.isAlive()) {
					basemodelTempList.add(model);
				}
			}
			for (BaseModel model : gamelayout4plant1) {
				if (!model.isAlive()) {
					basemodelTempList.add(model);
				}
			}
			for (BaseModel model : gamelayout4plant2) {
				if (!model.isAlive()) {
					basemodelTempList.add(model);
				}
			}
			for (BaseModel model : gamelayout4plant3) {
				if (!model.isAlive()) {
					basemodelTempList.add(model);
				}
			}
			for (BaseModel model : gamelayout4plant4) {
				if (!model.isAlive()) {
					basemodelTempList.add(model);
				}
			}
			for (BaseModel model : gamelayout1) {
				if (!model.isAlive()) {
					basemodelTempList.add(model);
				}
			}
			for (BaseModel model : gamelayout2) {
				if (!model.isAlive()) {
					basemodelTempList.add(model);
				}
			}
			
			for (BaseModel model : gamelayout3) {
				if (!model.isAlive()) {
					basemodelTempList.add(model);
				}
			}
			
			for (BaseModel deadModel : basemodelTempList) {
				gamelayout1.remove(deadModel);
				gamelayout2.remove(deadModel);
				gamelayout3.remove(deadModel);
				gamelayout4zombie0.remove(deadModel);
				gamelayout4zombie1.remove(deadModel);
				gamelayout4zombie2.remove(deadModel);
				gamelayout4zombie3.remove(deadModel);
				gamelayout4zombie4.remove(deadModel);
				gamelayout4plant0.remove(deadModel);
				gamelayout4plant1.remove(deadModel);
				gamelayout4plant2.remove(deadModel);
				gamelayout4plant3.remove(deadModel);
				gamelayout4plant4.remove(deadModel);
			}
		}
	}

	private void onDraw() {
		// TODO Auto-generated method stub
		synchronized (surfaceHolder) {
			try {
				canvas = surfaceHolder.lockCanvas();
				bkcCanvas.drawBitmap(Config.gameback, 0, 0, paint);
				bkcCanvas.drawBitmap(Config.seedBank, (Config.deviceWith - Config.seedBank.getWidth())/2, 0, paint);
				for (BaseModel model : gamelayout4plant0) {
					model.drawSelf(bkcCanvas, paint);
				}
				for (BaseModel model : gamelayout4zombie0) {
					model.drawSelf(bkcCanvas, paint);
				}
				for (BaseModel model : gamelayout4plant1) {
					model.drawSelf(bkcCanvas, paint);
				}
				for (BaseModel model : gamelayout4zombie1) {
					model.drawSelf(bkcCanvas, paint);
				}
				for (BaseModel model : gamelayout4plant2) {
					model.drawSelf(bkcCanvas, paint);
				}
				for (BaseModel model : gamelayout4zombie2) {
					model.drawSelf(bkcCanvas, paint);
				}
				for (BaseModel model : gamelayout4plant3) {
					model.drawSelf(bkcCanvas, paint);
				}
				for (BaseModel model : gamelayout4zombie3) {
					model.drawSelf(bkcCanvas, paint);
				}
				for (BaseModel model : gamelayout4plant4) {
					model.drawSelf(bkcCanvas, paint);
				}
				for (BaseModel model : gamelayout4zombie4) {
					model.drawSelf(bkcCanvas, paint);
				}
				
				for (BaseModel model : gamelayout3) {
					model.drawSelf(bkcCanvas, paint);
				}
				
				for (BaseModel model : gamelayout2) {
					model.drawSelf(bkcCanvas, paint);
				}
				for (BaseModel model : gamelayout1) {
					model.drawSelf(bkcCanvas, paint);
				}
				canvas.drawBitmap(buffer, 0, 0, paint);
			} catch (Exception e) {
			} finally {
				if (canvas != null) {
					surfaceHolder.unlockCanvasAndPost(canvas);
				}
			}
		}
	}
	
	@Override
	public boolean onTouchEvent(MotionEvent event) {
		// TODO Auto-generated method stub
		synchronized (surfaceHolder) {
			for (BaseModel model : gamelayout1) {
				if (model instanceof TouchAble) {
					if (((TouchAble) model).onTouch(event)) {
						return true;
					}
				}
			}
			for (BaseModel model : gamelayout2) {
				if (model instanceof TouchAble) {
					if (((TouchAble) model).onTouch(event)) {
						return true;
					}
				}
			}
			for (BaseModel model : gamelayout3) {
				if (model instanceof TouchAble) {
					if (((TouchAble) model).onTouch(event)) {
						return true;
					}
				}
			}
			return false;
		}
	}
	
	public static GameView getInstance () {
		return gameView;
	}

	public void apply4EmplacePlant(PlantType type, int locationX, int locationY) {
		// TODO Auto-generated method stub
		synchronized (surfaceHolder) {
			if (gamelayout1.size() == 0) {
				if (type == PlantType.FLOWER) {
					gamelayout1.add(new EmplacePlant(locationX, locationY, type));
				} else {
					gamelayout1.add(new EmplacePlant(locationX, locationY, type));
				}
			}
		}
	}

	public void apply4Plant(int locationX, int locationY, PlantType type) {
		// TODO Auto-generated method stub
		synchronized (surfaceHolder) {
			Point point;
			int raceWay = 0;
			for (Integer key : Config.plantPoints.keySet()) {
				point = Config.plantPoints.get(key);
				if ((Math.abs(locationX - point.x) < Config.gameback.getWidth() / 11 / 2)
						&& (Math.abs(locationY - point.y) < Config.gameback.getHeight() / 6 / 2)) {
					for (int i=0; i<Config.raceWayYpoints.length; i++) {
						if (point.y == Config.raceWayYpoints[i]) {
							raceWay = i;
							break;
						}
					}
					switch (raceWay) {
					case 0:
						if (checkAlreadyExitMapIndex(gamelayout4plant0, key)) {
							if (type == PlantType.FLOWER) {
								gamelayout4plant0.add(new Flower(point.x, point.y, key));
							} else {
								gamelayout4plant0.add(new Pea(point.x, point.y, key, raceWay));
							}
						}
						break;
					case 1:
						if (checkAlreadyExitMapIndex(gamelayout4plant1, key)) {
							if (type == PlantType.FLOWER) {
								gamelayout4plant1.add(new Flower(point.x, point.y, key));
							} else {
								gamelayout4plant1.add(new Pea(point.x, point.y, key, raceWay));
							}
						}
						break;
					case 2:
						if (checkAlreadyExitMapIndex(gamelayout4plant2, key)) {
							if (type == PlantType.FLOWER) {
								gamelayout4plant2.add(new Flower(point.x, point.y, key));
							} else {
								gamelayout4plant2.add(new Pea(point.x, point.y, key, raceWay));
							}
						}
						break;
					case 3:
						if (checkAlreadyExitMapIndex(gamelayout4plant3, key)) {
							if (type == PlantType.FLOWER) {
								gamelayout4plant3.add(new Flower(point.x, point.y, key));
							} else {
								gamelayout4plant3.add(new Pea(point.x, point.y, key, raceWay));
							}
						}
						break;
					case 4:
						if (checkAlreadyExitMapIndex(gamelayout4plant4, key)) {
							if (type == PlantType.FLOWER) {
								gamelayout4plant4.add(new Flower(point.x, point.y, key));
							} else {
								gamelayout4plant4.add(new Pea(point.x, point.y, key, raceWay));
							}
						}
						break;
					default:
						break;
					}
				}
			}
		}
	}

	private boolean checkAlreadyExitMapIndex(ArrayList<BaseModel> baseModels, int mapIndex) {
		// TODO Auto-generated method stub
		for (BaseModel model : baseModels) {
			if (model instanceof Plant) {
				if (((Plant) model).getMapIndex() == mapIndex) {
					return false;
				}
			}
		}
		return true;
	}

	public void givebirth2Sun(int locationX, int locationY) {
		// TODO Auto-generated method stub
		synchronized (surfaceHolder) {
			gamelayout3.add(new Sun(locationX, locationY));
		}
	}

	public void apply4Fire(int raceWay, int locationX, int locationY) {
		// TODO Auto-generated method stub
		synchronized (surfaceHolder) {
			switch (raceWay) {
			case 0:
				gamelayout4plant0.add(new Bullet(locationX, locationY));
				break;
			case 1:
				gamelayout4plant1.add(new Bullet(locationX, locationY));
				break;
			case 2:
				gamelayout4plant2.add(new Bullet(locationX, locationY));
				break;
			case 3:
				gamelayout4plant3.add(new Bullet(locationX, locationY));
				break;
			case 4:
				gamelayout4plant4.add(new Bullet(locationX, locationY));
				break;
			default:
				break;
			}
		}
	}

	public void givebirth2Zombie() {
		// TODO Auto-generated method stub
		synchronized (surfaceHolder) {
			int zombieRaceWay = (int)(Math.random() * 4);
			int height = (Config.zombieFrames[0].getHeight() - Config.flowerFrames[0].getHeight());
			switch (zombieRaceWay) {
			case 0:
				gamelayout4zombie0.add(new Zombie(Config.deviceWith + 20, Config.raceWayYpoints[zombieRaceWay] - height, zombieRaceWay));
				break;
			case 1:
				gamelayout4zombie1.add(new Zombie(Config.deviceWith + 20, Config.raceWayYpoints[zombieRaceWay] - height, zombieRaceWay));
				break;
			case 2:
				gamelayout4zombie2.add(new Zombie(Config.deviceWith + 20, Config.raceWayYpoints[zombieRaceWay] - height, zombieRaceWay));
				break;
			case 3:
				gamelayout4zombie3.add(new Zombie(Config.deviceWith + 20, Config.raceWayYpoints[zombieRaceWay] - height, zombieRaceWay));
				break;
			case 4:
				gamelayout4zombie4.add(new Zombie(Config.deviceWith + 20, Config.raceWayYpoints[zombieRaceWay] - height, zombieRaceWay));
				break;
			default:
				break;
			}
		}
	}

	public void checkCollision(Zombie zombie, int raceWay) {
		// TODO Auto-generated method stub
		synchronized (surfaceHolder) {
			switch (raceWay) {
//			| (x1 + w1 / 2) – (x2 + w2/2) | < |(w1 + w2) / 2|
//			矩形1的参数是：左上角的坐标是(x1,y1)，宽度是w1;矩形2的参数是：左上角的坐标是(x2,y2)，宽度是w2。
			case 0:
				for (BaseModel model : gamelayout4plant0) {
					if (Math.abs((model.getLocationX() + model.getModelWidth()/2) - (zombie.getLocationX() + zombie.getModelWidth()/2))
							< Math.abs((model.getModelWidth() + zombie.getModelWidth())/2)) {
						if (model instanceof Bullet) {
							zombie.setAlive(false);
						}
						model.setAlive(false);
					}
				}
				break;
			case 1:
				for (BaseModel model : gamelayout4plant1) {
					if (Math.abs((model.getLocationX() + model.getModelWidth()/2) - (zombie.getLocationX() + zombie.getModelWidth()/2))
							< Math.abs((model.getModelWidth() + zombie.getModelWidth())/2)) {
						if (model instanceof Bullet) {
							zombie.setAlive(false);
						}
						model.setAlive(false);
					}
				}
				break;
			case 2:
				for (BaseModel model : gamelayout4plant2) {
					if (Math.abs((model.getLocationX() + model.getModelWidth()/2) - (zombie.getLocationX() + zombie.getModelWidth()/2))
							< Math.abs((model.getModelWidth() + zombie.getModelWidth())/2)) {
						if (model instanceof Bullet) {
							zombie.setAlive(false);
						}
						model.setAlive(false);
					}
				}
				break;
			case 3:
				for (BaseModel model : gamelayout4plant3) {
					if (Math.abs((model.getLocationX() + model.getModelWidth()/2) - (zombie.getLocationX() + zombie.getModelWidth()/2))
							< Math.abs((model.getModelWidth() + zombie.getModelWidth())/2)) {
						if (model instanceof Bullet) {
							zombie.setAlive(false);
						}
						model.setAlive(false);
					}
				}
				break;
			case 4:
				for (BaseModel model : gamelayout4plant4) {
					if (Math.abs((model.getLocationX() + model.getModelWidth()/2) - (zombie.getLocationX() + zombie.getModelWidth()/2))
							< Math.abs((model.getModelWidth() + zombie.getModelWidth())/2)) {
						if (model instanceof Bullet) {
							zombie.setAlive(false);
						}
						model.setAlive(false);
					}
				}
				break;
			default:
				break;
			}
		}
	}
}
